#ifndef ARCHIVODOCUMENTOS_H_
#define ARCHIVODOCUMENTOS_H_


#include "indexes/ArbolBMas.h"
#include "indexes/Registro.h"
#include <string>

#ifndef ID_DOCUMENTO
#define ID_DOCUMENTO "idDocumento"
#endif

#ifndef OFFSET
#define OFFSET "offset"
#endif

/*
 * Clase que define la clave del indice principal
 */
class RegRutaDocumento : public Registro
{
private:
	string strRuta;
public:
	static fstream* rutaDocs;
	RegRutaDocumento(const long num = 0)
	{
		(*this)[OFFSET] = (long) num;
		this->strRuta = "";
	}
	long getOffset() {return *((long*) ((*this)[OFFSET].getValor()));}
	void setOffset(long f){(*this)[OFFSET]=f;}
	void setRuta(string& rutaDoc) { this->strRuta = rutaDoc; }
	string getRuta() const { return this->strRuta; }
	
	string readRuta() {
		long offset = this->getOffset();
		unsigned longRuta;
		char* ruta;
		string sruta;
		
		if(offset > 0) {
			this->rutaDocs->seekg(offset);
			this->rutaDocs->read((char*) &longRuta, sizeof(longRuta));
			ruta = new char[longRuta];
			this->rutaDocs->read((char*) ruta, longRuta);
			sruta = ruta;
			delete[] ruta;
		}
		else
			sruta = "";
		
		this->setRuta(sruta);
		return sruta;
	}
	
	void writeRuta(string& rutaDoc) {
		long offset;
		unsigned longRuta = rutaDoc.length() + 1;
		
		this->rutaDocs->seekp(0,fstream::end);
		offset = this->rutaDocs->tellg();
		this->rutaDocs->write((char*) &longRuta, sizeof(longRuta));
		this->rutaDocs->write((char*) rutaDoc.c_str(), longRuta);
		this->setOffset(offset);
		this->setRuta(rutaDoc);		
	}
	
	bool operator==(const RegRutaDocumento &registro) const{
		string a,b;
		
		if (const_cast<RegRutaDocumento*>(this)->getOffset() == 0)
			a = this->getRuta();
		else
		    a = const_cast<RegRutaDocumento*>(this)->readRuta();
		
		if (const_cast<RegRutaDocumento*>(&registro)->getOffset() == 0)
			b = registro.getRuta();
		else
		    b = const_cast<RegRutaDocumento*>(&registro)->readRuta();

		return (a == b);
	}
	bool operator<(const RegRutaDocumento &registro) const {
	string a,b;
		
		if (const_cast<RegRutaDocumento*>(this)->getOffset() == 0)
			a = this->getRuta();
		else
		    a = const_cast<RegRutaDocumento*>(this)->readRuta();
		
		if (const_cast<RegRutaDocumento*>(&registro)->getOffset() == 0)
			b = registro.getRuta();
		else 
		    b = const_cast<RegRutaDocumento*>(&registro)->readRuta();
		    
		return (a < b);
	}

	RegRutaDocumento& operator=(const RegRutaDocumento &registro)
	{
		if (!(this==&registro))
		{	
			this->nombresCampos=registro.nombresCampos;
			this->campos=registro.campos;
			this->strRuta = registro.strRuta; 
		}

		return *this;
	}
	
};


/*
 * Clase que define el dato del indice principal
 */
class RegIdDocumento : public Registro
{
public:
	
	RegIdDocumento(const long num=1)
	{
		(*this)[ID_DOCUMENTO] = (long) num;
	}
	long getIdDocumento(){return *((long*) ((*this)[ID_DOCUMENTO].getValor()));}
	void setIdDocumento(long f){(*this)[ID_DOCUMENTO]=f;}
	
};


class archivoDocumentos
{
private:
	ArbolBMas<RegRutaDocumento,RegIdDocumento> indice;
	ArbolBMas<RegIdDocumento,RegRutaDocumento> indiceSec; //indice secundario
	long cantDocumentos;
	fstream rutaDocumentos;
public:
	archivoDocumentos(string ruta, string rutasec);
	~archivoDocumentos();
	/* agrega ruta de doc, devuelve idDoc */
	long agregarDocumento(string& rutaDoc);
	/* dada una ruta, devuelve su idDoc  */
	long obtenerIdDocumento(string& rutaDoc);
	/* dada un idDoc, devuelve su ruta  */
	string obtenerRutaDocumento(long idDoc);
	/* obtiene la cantidad de documentos */
	long getCantDocumentos();
};

#endif /*ARCHIVODOCUMENTOS_H_*/
